import * as os from 'os';
import {NetworkInterfaceBase} from 'os';

/**
 * 选择配置
 */
interface SelectorOptions {
  /**
   * 首选
   */
  preferred?: string[];
  /**
   * 忽略
   */
  ignore?: string[];
  /**
   * 网络类型
   */
  family?: 'IPv4' | 'IPv6';
}

/**
 * 网络地址信息
 */
interface NetworkInterface extends NetworkInterfaceBase {
  /**
   * 网络类型
   */
  family: string;
  /**
   * ipv6 scopeid
   */
  scopeid?: number;
  /**
   * 网卡名称
   */
  displayName: string;
}

/**
 * 获取网络地址列表
 * @return 网络地址列表
 */
export function getNetworkInterfaces(): NetworkInterface[] {
  const interfaces: NetworkInterface[] = [];
  const networks = os.networkInterfaces();
  for (const networkName in networks) {
    for (const index in networks[networkName]) {
      interfaces.push({
        ...networks[networkName][index],
        displayName: networkName
      });
    }
  }

  return interfaces;
}

/**
 * 获取网络地址，如无网络地址则返回null
 * @param options 选择配置
 * @return 当前网络地址
 */
export function getNetworkInterface(options?: SelectorOptions): NetworkInterface {
  const family: string | null = options && options.family ? options.family : null;
  const ignore: string[] = options && options.ignore ? options.ignore : [];
  const preferred: string[] = options && options.preferred ? options.preferred : [];

  const result: NetworkInterface[] = [];

  const networkInterfaces = getNetworkInterfaces();
  for (const index in networkInterfaces) {
    const instance = networkInterfaces[index];

    if (instance.internal) {
      continue;
    }

    if (family && instance.family !== family) {
      continue;
    }

    if (isIgnore(instance.displayName, ignore)) {
      continue;
    }

    if (isPreferred(instance.address, preferred)) {
      return instance;
    }

    result.push(instance);
  }

  if (result.length > 0) {
    return result[0];
  } else {
    throw new Error('not found networkInterface');
  }
}

/**
 * 判断是否为首选地址
 * @param address 地址
 * @param preferred 首选列表
 */
function isPreferred(address: string, preferred: string[]): boolean {
  if (preferred && preferred.length > 0) {
    for (const index in preferred) {
      const regex = new RegExp(preferred[index]);
      if (regex.test(address)) {
        return true;
      }
    }
  }
  return false;
}

/**
 * 判断是否为忽略网卡
 * @param name 网卡名称
 * @param ignore 忽略列表
 */
function isIgnore(name: string, ignore: string[]): boolean {
  if (ignore && ignore.length > 0) {
    for (const index in ignore) {
      const regex = new RegExp(ignore[index]);
      if (regex.test(name)) {
        return true;
      }
    }
  }

  return false;
}
